package com.baomidou.mybatisplus.criterion;

import java.util.Collection;

/**
 * criterion包的目标是用于以面向对象的形式构造SQL语句<br/>
 * 查询条件的构造是核心，而绝大部分可以直接使用Restrictions类提供的静态方式就实现
 * @author Timothy Ren
 */
public class Restrictions {

	Restrictions() {
		// cannot be instantiated
	}

	/**
	 * Apply an "equal" constraint to the named property
	 * @param propertyName The name of the property
	 * @param value The value to use in comparison
	 * @return The SimpleExpression
	 */
	public static SimpleExpression eq(String propertyName, Object value) {
		return new SimpleExpression(propertyName, value, "=");
	}

	/**
	 * Apply an "equal" constraint to the named property. If the value
	 * is null, instead apply "is null".
	 * @param propertyName The name of the property
	 * @param value The value to use in comparison
	 * @return The QueryCriterion
	 */
	public static QueryCriterion eqOrIsNull(String propertyName, Object value) {
		return value == null ? isNull(propertyName) : eq(propertyName, value);
	}

	/**
	 * Apply a "not equal" constraint to the named property
	 * @param propertyName The name of the property
	 * @param value The value to use in comparison
	 * @return The SimpleExpression
	 */
	public static SimpleExpression ne(String propertyName, Object value) {
		return new SimpleExpression(propertyName, value, "<>");
	}

	/**
	 * Apply a "not equal" constraint to the named property. If the value
	 * is null, instead apply "is not null".
	 * @param propertyName The name of the property
	 * @param value The value to use in comparison
	 * @return The QueryCriterion
	 */
	public static QueryCriterion neOrIsNotNull(String propertyName, Object value) {
		return value == null ? isNotNull(propertyName) : ne(propertyName, value);
	}

	/**
	 * Apply a "like" constraint to the named property
	 * @param propertyName The name of the property
	 * @param value The value to use in comparison
	 * @return The SimpleExpression
	 */
	public static SimpleExpression like(String propertyName, Object value) {
		return new SimpleExpression(propertyName, value, " like ");
	}

	/**
	 * Apply a "like" constraint to the named property
	 * @param propertyName The name of the property
	 * @param value The value to use in comparison
	 * @param matchMode The match mode to use in comparison
	 * @return The SimpleExpression
	 */
	public static SimpleExpression like(String propertyName, String value, MatchMode matchMode) {
		return new SimpleExpression(propertyName, matchMode.toMatchString(value), " like ");
	}

	/**
	 * Apply a "not like" constraint to the named property
	 * @param propertyName The name of the property
	 * @param value The value to use in comparison
	 * @return The SimpleExpression
	 */
	public static SimpleExpression notLike(String propertyName, Object value) {
		return new SimpleExpression(propertyName, value, " not like ");
	}

	/**
	 * Apply a "not like" constraint to the named property
	 * @param propertyName The name of the property
	 * @param value The value to use in comparison
	 * @param matchMode The match mode to use in comparison
	 * @return The SimpleExpression
	 */
	public static SimpleExpression notLike(String propertyName, String value, MatchMode matchMode) {
		return new SimpleExpression(propertyName, matchMode.toMatchString(value), " not like ");
	}

	/**
	 * Apply a "greater than" constraint to the named property
	 * @param propertyName The name of the property
	 * @param value The value to use in comparison
	 * @return The SimpleExpression
	 */
	public static SimpleExpression gt(String propertyName, Object value) {
		return new SimpleExpression(propertyName, value, ">");
	}

	/**
	 * Apply a "less than" constraint to the named property
	 * @param propertyName The name of the property
	 * @param value The value to use in comparison
	 * @return The SimpleExpression
	 */
	public static SimpleExpression lt(String propertyName, Object value) {
		return new SimpleExpression(propertyName, value, "<");
	}

	/**
	 * Apply a "less than or equal" constraint to the named property
	 * @param propertyName The name of the property
	 * @param value The value to use in comparison
	 * @return The SimpleExpression
	 */
	public static SimpleExpression le(String propertyName, Object value) {
		return new SimpleExpression(propertyName, value, "<=");
	}

	/**
	 * Apply a "greater than or equal" constraint to the named property
	 * @param propertyName The name of the property
	 * @param value The value to use in comparison
	 * @return The SimpleExpression
	 */
	public static SimpleExpression ge(String propertyName, Object value) {
		return new SimpleExpression(propertyName, value, ">=");
	}

	/**
	 * Apply a "between" constraint to the named property
	 * @param propertyName The name of the property
	 * @param lo The low value
	 * @param hi The high value
	 * @return The QueryCriterion
	 */
	public static QueryCriterion between(String propertyName, Object lo, Object hi) {
		return new BetweenExpression(propertyName, lo, hi);
	}

	/**
	 * Apply an "in" constraint to the named property
	 * @param propertyName The name of the property
	 * @param values The literal values to use in the IN restriction
	 * @return The QueryCriterion
	 */
	public static QueryCriterion in(String propertyName, Object... values) {
		return new InExpression(propertyName, values);
	}

	/**
	 * Apply an "in" constraint to the named property
	 * @param propertyName The name of the property
	 * @param values The literal values to use in the IN restriction
	 * @return The QueryCriterion
	 */
	public static QueryCriterion in(String propertyName, Collection values) {
		return new InExpression(propertyName, values.toArray());
	}

	/**
	 * Apply an "not in" constraint to the named property
	 * @param propertyName The name of the property
	 * @param values The literal values to use in the IN restriction
	 * @return The QueryCriterion
	 */
	public static QueryCriterion notIn(String propertyName, Object... values) {
		return new NotInExpression(propertyName, values);
	}

	/**
	 * Apply an "not in" constraint to the named property
	 * @param propertyName The name of the property
	 * @param values The literal values to use in the IN restriction
	 * @return The QueryCriterion
	 */
	public static QueryCriterion notIn(String propertyName, Collection values) {
		return new NotInExpression(propertyName, values.toArray());
	}

	/**
	 * Apply an "is null" constraint to the named property
	 * @param propertyName The name of the property
	 * @return The QueryCriterion
	 */
	public static QueryCriterion isNull(String propertyName) {
		return new NullExpression(propertyName);
	}

	/**
	 * Apply an "is not null" constraint to the named property
	 * @param propertyName The name of the property
	 * @return The QueryCriterion
	 */
	public static QueryCriterion isNotNull(String propertyName) {
		return new NotNullExpression(propertyName);
	}

	/**
	 * Apply an "equal" constraint to two properties
	 * @param propertyName One property name
	 * @param otherPropertyName The other property name
	 * @return The PropertyExpression
	 */
	public static PropertyExpression eqProperty(String propertyName, String otherPropertyName) {
		return new PropertyExpression(propertyName, otherPropertyName, "=");
	}

	/**
	 * Apply a "not equal" constraint to two properties
	 * @param propertyName One property name
	 * @param otherPropertyName The other property name
	 * @return The PropertyExpression
	 */
	public static PropertyExpression neProperty(String propertyName, String otherPropertyName) {
		return new PropertyExpression(propertyName, otherPropertyName, "<>");
	}

	/**
	 * Apply a "less than" constraint to two properties
	 * @param propertyName One property name
	 * @param otherPropertyName The other property name
	 * @return The PropertyExpression
	 */
	public static PropertyExpression ltProperty(String propertyName, String otherPropertyName) {
		return new PropertyExpression(propertyName, otherPropertyName, "<");
	}

	/**
	 * Apply a "less than or equal" constraint to two properties
	 * @param propertyName One property name
	 * @param otherPropertyName The other property name
	 * @return The PropertyExpression
	 */
	public static PropertyExpression leProperty(String propertyName, String otherPropertyName) {
		return new PropertyExpression(propertyName, otherPropertyName, "<=");
	}

	/**
	 * Apply a "greater than" constraint to two properties
	 * @param propertyName One property name
	 * @param otherPropertyName The other property name
	 * @return The PropertyExpression
	 */
	public static PropertyExpression gtProperty(String propertyName, String otherPropertyName) {
		return new PropertyExpression(propertyName, otherPropertyName, ">");
	}

	/**
	 * Apply a "greater than or equal" constraint to two properties
	 * @param propertyName One property name
	 * @param otherPropertyName The other property name
	 * @return The PropertyExpression
	 */
	public static PropertyExpression geProperty(String propertyName, String otherPropertyName) {
		return new PropertyExpression(propertyName, otherPropertyName, ">=");
	}

	/**
	 * Return the conjuction of two expressions
	 * @param lhs One expression
	 * @param rhs The other expression
	 * @return The LogicalExpression
	 */
	public static LogicalExpression and(QueryCriterion lhs, QueryCriterion rhs) {
		return new LogicalExpression("and", lhs, rhs);
	}

	/**
	 * 多个查询条件之间and 连接
	 * @param criterions 查询条件集合
	 * @return The LogicalExpression
	 */
	public static LogicalExpression and(QueryCriterion... criterions) {
		return new LogicalExpression("and", criterions);
	}

	/**
	 * Return the disjuction of two expressions
	 * @param lhs One expression
	 * @param rhs The other expression
	 * @return The LogicalExpression
	 */
	public static LogicalExpression or(QueryCriterion lhs, QueryCriterion rhs) {
		return new LogicalExpression("or", lhs, rhs);
	}

	/**
	 * 多个查询条件之间or 连接
	 * @param criterions 查询条件集合
	 * @return The LogicalExpression
	 */
	public static LogicalExpression or(QueryCriterion... criterions) {
		return new LogicalExpression("or", criterions);
	}

	/**
	 * Return the negation of an expression
	 * @param expression The expression to be negated
	 * @return The NotExpression
	 */
	public static NotExpression not(QueryCriterion expression) {
		return new NotExpression(expression);
	}

}
